#include "Sock.hpp"
#include <poll.h>

#define NUM 128
struct pollfd fd_num[NUM];

void Usage(char* arg){
	std::cout<<"Usage:"<<arg<<" port"<<std::endl;
}

int main(int argc,char* argv[]){
	if(argc != 2){
		Usage(argv[0]);
	}

	uint16_t port =(uint16_t)atoi(argv[1]);
	int listen_sock =  Sock::SOCKET();
	Sock::BIND(listen_sock,port);
	Sock::LISTEN(listen_sock);

	//init fd_num[i];
  for(unsigned int i = 0;i<NUM;i++){
    fd_num[i].fd = -1;
    fd_num[i].events = fd_num[i].revents = 0;
  }

    
	fd_num[0].fd= listen_sock;
  fd_num[0].events |= POLLIN; 
  fd_num[0].revents = 0;

	for(;;){
    int n = poll(fd_num,(nfds_t)NUM,1000);
    
		switch(n){
			case -1:
				std::cerr<<"select error"<<std::endl;
				break;
			case 0:
				std::cerr<<"select timeout"<<std::endl;
				break;
			default:
				std::cout<<"select ready"<<std::endl;
        
        for(unsigned int i = 0;i<NUM;i++){
          if(fd_num[i].fd < 0){continue;}

          // determine whether the value of rfds is valid;
          
          if(fd_num[i].revents & POLLIN){
            std::cout<<"read event is ready"<<std::endl;

            //Here should determine whether the value of fd_num[i] is equal to listen_sock;
            
             if(fd_num[i].fd == listen_sock){
               std::cout<<"listen_sock : "<<listen_sock<<", new link is ready"<<std::endl;
               int sock = Sock::ACCEPT(listen_sock);
                  
               std::cout<<"listen_sock : "<<listen_sock<<", new link has got success"<<std::endl;

                  // we got the `sock`,but that doesn't mean you can start using `read ,recv ...`
                  // beacuse we don't know if the data in this new `sock`  is ready;
                  // so we need continuly to use select to reduce the account of time spend in blocking wait;
                  
                  unsigned int pos =1;
                  for(;pos<NUM;pos++){
                    if(fd_num[pos].fd<0){break;}
                  }

                  // if pos less than NUM ,indicate that this location is empty;
                
                  if(pos < NUM){
                    std::cout<<"new sock : "<<sock<<", has been added to fd_num"<<std::endl;
                    fd_num[pos].fd = sock;
                    fd_num[pos].events |= POLLIN;
                  }
                  else{ //if pos greater than or equal to NUM,indicate that the server had be full;
                    close(sock);
                  }
             }
             else{
                 // here is common sock;
                 // we can read context directly
                 // but it's not certain that we can read it all  at once 
                 // so,for demonstration purposes,we assume that could read it all;
                 
               char recv_buffer[1024];
               size_t s = recv(fd_num[i].fd,recv_buffer,sizeof(recv_buffer)-1,0);
               if(s > 0){
                 /* read success */

                 recv_buffer[s]= 0;
                 std::cout<<"client : "<< fd_num[i].fd<<",recv messages:"<<recv_buffer<<std::endl;
               } 
               else if(s == 0){  //client has close 
                 //server also close sock,and delete sock from fd_num;
                 close(fd_num[i].fd);
                 fd_num[i].fd = -1;
                 fd_num[i].events = fd_num[i].revents = 0;
                 std::cout<<"client has close and server also has delete sock from fd_num[i]"<<std::endl;
               }
               else {
                 //read error;
               }
             }
          }
        }
				break;
		}
	}
	return 0;
}
